package com.jf.anmocker.plugin.transform;

import com.android.build.api.transform.Context;
import com.android.build.api.transform.DirectoryInput;
import com.android.build.api.transform.Format;
import com.android.build.api.transform.JarInput;
import com.android.build.api.transform.QualifiedContent;
import com.android.build.api.transform.Transform;
import com.android.build.api.transform.TransformException;
import com.android.build.api.transform.TransformInput;
import com.android.build.api.transform.TransformOutputProvider;
import com.android.build.gradle.internal.pipeline.TransformManager;
import com.jf.anmocker.plugin.injector.AMInjector;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.gradle.api.Project;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Set;

/**
 * @Class: MyTransfrom
 * @Description:
 * @author:
 * @Date: 2022/9/21
 */
public class MyTransform extends Transform {

    private final Project project;
    private final AMInjector injector;
    private static final boolean INJECT_JAR = false;

    public MyTransform(Project project) {
        this.project = project;
        this.injector = new AMInjector(project);
        printCopyRight();
    }

    // 指定 Transform 的名称，该名称还会用于组成 Task 的名称
    // 格式为 transform[InputTypes]With[name]For[Configuration]
    @Override
    public String getName() {
        return "TransformWithMyScan";
    }

    /**
     * 需要处理的数据类型，有两种枚举类型
     * CLASSES 代表处理的 java 的 class 文件，RESOURCES 代表要处理 java 的资源
     * @return
     */
    @Override
    public Set<QualifiedContent.ContentType> getInputTypes() {
        return TransformManager.CONTENT_CLASS;
    }

    /**
     * 指 Transform 要操作内容的范围，官方文档 Scope 有 7 种类型：
     * 1. EXTERNAL_LIBRARIES        只有外部库
     * 2. PROJECT                   只有项目内容
     * 3. PROJECT_LOCAL_DEPS        只有项目的本地依赖(本地jar)
     * 4. PROVIDED_ONLY             只提供本地或远程依赖项
     * 5. SUB_PROJECTS              只有子项目。
     * 6. SUB_PROJECTS_LOCAL_DEPS   只有子项目的本地依赖项(本地jar)。
     * 7. TESTED_CODE               由当前变量(包括依赖项)测试的代码
     * @return
     */
    @Override
    public Set<? super QualifiedContent.Scope> getScopes() {
        return TransformManager.SCOPE_FULL_PROJECT;
    }

    // 指定是否支持增量编译
    @Override
    public boolean isIncremental() {
        return false;
    }

    /**
     * 打印提示信息
     */
    static void printCopyRight() {
        System.out.println();
        System.out.println("####################################################################");
        System.out.println("########                                                    ########");
        System.out.println("########                                                    ########");
        System.out.println("########              欢迎使用 MyPlugin 编译插件            ########");
        System.out.println("########              使用过程中碰到任何问题请联系我们            ########");
        System.out.println("########                                                     ########");
        System.out.println("########                                                     ########");
        System.out.println("#####################################################################");
        System.out.println();
    }

    // 核心 API
    public void transform(Context context, Collection<TransformInput> inputs,
            Collection<TransformInput> referencedInputs,
            TransformOutputProvider outputProvider,
            boolean isIncremental) throws IOException, TransformException, InterruptedException {
        //增量判断
        if(!isIncremental){
            outputProvider.deleteAll();
        }
        System.out.println("---------- transform from MyTransform !---------");
        // Transform 的 inputs 有两种类型，一种是目录，一种是 jar 包，要分开遍历
        inputs.forEach(input -> {            //遍历JAR
            readJarInputs(outputProvider, input.getJarInputs());
            //遍历目录
            readDirectoryInputs(outputProvider, input.getDirectoryInputs());
        });
    }

    private void readDirectoryInputs(TransformOutputProvider outputProvider, Collection<DirectoryInput> directoryInputs){
        //System.out.println("Transform directoryInputs start.");
        directoryInputs.forEach(directoryInput -> {
            //遍历开始
            System.out.println("directoryInputs >>> " + directoryInput.getFile().getAbsolutePath());
            //处理文件类
            injector.collectClassFileFromDir(directoryInput.getFile());
            //開始处理注入替代
            injector.injectCollectClasses();
            try {
                //获取 output 目录
                File dest = outputProvider.getContentLocation(directoryInput.getName(),
                        directoryInput.getContentTypes(), directoryInput.getScopes(),
                        Format.DIRECTORY);
                //将 input 的目录复制到 output 指定目录
                FileUtils.copyDirectory(directoryInput.getFile(), dest);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    private void readJarInputs(TransformOutputProvider outputProvider, Collection<JarInput> jarInputS){
        System.out.println("Transform jarInputs start.");
        jarInputS.forEach(jarInput -> {
            /**重命名输出文件（同目录copyFile会冲突）*/
            String destName = jarInput.getFile().getName();
            //遍历开始
            System.out.println("jarInputs >>> " + destName);
            /**截取文件路径的 md5 值重命名输出文件,因为可能同名,会覆盖*/
            String hexName = DigestUtils.md5Hex(jarInput.getFile().getAbsolutePath()).substring(0, 8);
            /** 获取 jar 名字*/
            if (destName.endsWith(".jar")) {
                destName = destName.substring(0, destName.length() - 4);
            }
            //不做任何改变输出
            File copyJarFile = jarInput.getFile();
            if(INJECT_JAR){
                //处理文件类
                injector.collectClassFileFromJar(jarInput.getFile());
                //更新内容
                //File copyJarFile = MyJarAnalyticsInjectG.injectJar(jarInput.getFile().getAbsolutePath(), project);
            }
            ////生成输出路径
            //File dest = outputProvider.getContentLocation(destName + hexName,
            //        jarInput.getContentTypes(), jarInput.getScopes(), Format.JAR);
            //1.4 获取输出的文件夹
            File dest = outputProvider.getContentLocation(
                    jarInput.getName(),
                    jarInput.getContentTypes(),
                    jarInput.getScopes(),
                    Format.JAR);
            // 将 input 的目录复制到 output 指定目录
            try {
                FileUtils.copyFile(copyJarFile, dest);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    // 指定是否支持缓存
    public boolean isCacheable() {
        return false;
    }

}
